/********************************************************
 Name          : file_system.c
 Author        : Khachatur Gyozalyan
 Copyright     : Copyright by Antel Systems
 Description   :
 **********************************************************/

#include "file_system.h"
#include "crc8.h"
#include "AntelCfgOID.h"
#include "Parameters.h"

const struct file_t files_list[MAX_FILE_COUNT] =
{
	{"CMXDB1_1", 0x0000,  44 * 1024, 1, IMAGE_FILE_TYPE},
	{"CMXDB1_2", 0x00B0,  20 * 1024, 1, IMAGE_FILE_TYPE},
	{"CMXDB2_1", 0x0100,  44 * 1024, 1, IMAGE_FILE_TYPE},
	{"CMXDB2_2", 0x01B0,  20 * 1024, 1, IMAGE_FILE_TYPE},
	{"CMXDB4_1", 0x0200,  44 * 1024, 1, IMAGE_FILE_TYPE},
	{"CMXDB4_2", 0x02B0,  20 * 1024, 1, IMAGE_FILE_TYPE},
	{"WLFW"    , 0x0300, 192 * 1024, 1, IMAGE_FILE_TYPE},
	{"CBTB"    , 0x0700,  32 * 1024, 1, CBTB_FILE_TYPE },
	{"FCFG"    , 0x07A0,   8 * 1024, 1, FCFG_FILE_TYPE },
	{"UCFG"    , 0x07C0,  14 * 1024, 1, UCFG_FILE_TYPE },
};

/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       find_file
  Description :       This function find file in file list.
  Return      :       int - 0 if success, 1 if file not found
  Parameters  :       file_t - founded file
                      char * - file name
  Note        :
\*================================================================================*/
int find_file(struct file_t *file,char * name)
{
	int i;
	for(i = 0 ; i < MAX_FILE_COUNT ; i++)
	{
		if (!strcmp(name,(char *)(files_list[i].name)))
			break;
	}
	if(i == MAX_FILE_COUNT)
		return 1;
	strcpy(file->name,files_list[i].name);
	file->sector_number = files_list[i].sector_number;
	file->max_size = files_list[i].max_size;
	file->file_exist = files_list[i].file_exist;
	file->file_type = files_list[i].file_type;
	return 0;
}

/*================================================================================*\
  Author      :       Khachatur Gyozalyan
  ================================================================================
  Function    :       check_file_header
  Description :       This function check file header crc8.
  Return      :       int - 1 if header nermal, 1 if error in header.
  Parameters  :       unsigned char * - pointer to file header.
                      unsigned char file_type
  Note        :
\*================================================================================*/
int check_file_header(unsigned char * ptr,struct file_t file)
{
	struct FileHeader * headre = (struct FileHeader *)ptr;
	unsigned char crc = Crc8ByTable(ptr,SIZEOF_FILEHEADER - 1);
	if(crc != headre->crc8)
		return 0;
	if(file.file_type != headre->Type)
		return 0;
	return 1;
}

int copy_from_flash_to_rom(unsigned int rom_address,unsigned int flash_address,unsigned int byte_count)
{
	unsigned char buffer[AT25DFX_SECTOR_SIZE];
	unsigned int sector_count = byte_count >> AT25DFX_SECTOR_BITS;
	int i;
	if((AVR32_FLASH_ADDRESS + AVR32_FLASH_SIZE - rom_address) < byte_count)
		byte_count = AVR32_FLASH_ADDRESS + AVR32_FLASH_SIZE - rom_address;
	for(i = 0 ; i < sector_count ; i++)
	{
		at25dfx_read_sector(flash_address + i,1,buffer);
		flashc_memcpy((void *)(rom_address + i * AT25DFX_SECTOR_SIZE),buffer, AT25DFX_SECTOR_SIZE,1);
	}
	return 0;
}

void loading_config(int boot_option)
{
	if(boot_option)
	{
		//copy_from_flash_to_rom(INTERNAL_USER_CFG_FILE_ADDRESS,files_list[FCFG_FILE_INDEX].sector_number,files_list[FCFG_FILE_INDEX].max_size - AT25DFX_SECTOR_SIZE);
	}
	else
	{
		//copy_from_flash_to_rom(INTERNAL_USER_CFG_FILE_ADDRESS,files_list[UCFG_FILE_INDEX].sector_number,files_list[UCFG_FILE_INDEX].max_size - AT25DFX_SECTOR_SIZE);
	}
	gBoot_option = boot_option;
}

void organize_files_operation(void)
{
	AvailableFiles = check_files_availability();

	if(!CALIB_TABLE_IS_AVALIABLE || !FACTORY_CONFIG_IS_AVALIABLE)
		StartupMode = START_UP_REQUIRE_WRITE;

	if(!USER_CONFIG_IS_AVALIABLE && CALIB_TABLE_IS_AVALIABLE && FACTORY_CONFIG_IS_AVALIABLE)
		StartupMode = START_UP_LOAD_DEFAULT;

	if(CALIB_TABLE_IS_AVALIABLE && FACTORY_CONFIG_IS_AVALIABLE && USER_CONFIG_IS_AVALIABLE)
		StartupMode = START_UP_NORMAL;
}

unsigned char check_files_availability(void)
{
	unsigned char result = 0;
	unsigned char buffer[SIZEOF_FILEHEADER];

	at25dfx_read_bytes(files_list[CBTB_FILE_INDEX].sector_number * AT25DFX_SECTOR_SIZE,SIZEOF_FILEHEADER,buffer);
	if(check_file_header(buffer,files_list[CBTB_FILE_INDEX]))
		result |= (1 << CBTB_Available);

	at25dfx_read_bytes(files_list[FCFG_FILE_INDEX].sector_number * AT25DFX_SECTOR_SIZE,SIZEOF_FILEHEADER,buffer);
	if(check_file_header(buffer,files_list[FCFG_FILE_INDEX]))
		result |= (1 << FCFG_Available);

	at25dfx_read_bytes(files_list[UCFG_FILE_INDEX].sector_number * AT25DFX_SECTOR_SIZE,SIZEOF_FILEHEADER,buffer);
	if(check_file_header(buffer,files_list[UCFG_FILE_INDEX]))
		result |= (1 << UCFG_Available);

	return result;
}

unsigned char save_ucfg(void)
{
	unsigned char * data;
	unsigned int local_address = 0;
	data = malloc(1024);
	if(!data)
		return 1;
	memset(data,0x00,1024);

	save_code_params();
	at25dfx_read_bytes(files_list[UCFG_FILE_INDEX].sector_number * AT25DFX_SECTOR_SIZE,SIZEOF_CANNEL_TABLE + SIZEOF_FILEHEADER,data);
	/////////////////////////////////////////////////////////////////
	local_address += SIZEOF_CANNEL_TABLE + SIZEOF_FILEHEADER - ConfigRoot.G_Wireless.SG_Uhf.param_channel_num * SIZEOF_CANNEL;
	//memcpy(&data[local_address],(unsigned char *)&(Current_Channel.freq),SIZEOF_FREQUENCY_CARRIER_NUMBER);
	local_address += SIZEOF_FREQUENCY_CARRIER_NUMBER;
	//memcpy(&data[local_address],(unsigned char *)&(Current_Channel.pow),SIZEOF_OUTPUT_POWER);
	local_address += SIZEOF_OUTPUT_POWER;
	//memcpy(&data[local_address],(unsigned char *)&(Current_Channel.sym_rate),SIZEOF_SYMBOL_RATE);
	local_address += SIZEOF_SYMBOL_RATE + (ConfigRoot.G_Wireless.SG_Uhf.param_channel_num - 1) * SIZEOF_CANNEL;
	//////////////////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_DeviceIndividualization),SIZEOF_DEVICE_INDIVIDUALIZATION);
	local_address += SIZEOF_DEVICE_INDIVIDUALIZATION;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_primary_interface_select),SIZEOF_PRIMARY_INTERFACE_SELECT);
	local_address += SIZEOF_PRIMARY_INTERFACE_SELECT;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Oper.SG_Data_Interface.param_interface_timeout,SIZEOF_INTERFACE_TIMEOUT);
	local_address += SIZEOF_INTERFACE_TIMEOUT;
	memcpy(&data[local_address],(unsigned int *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_baud_rate),SIZEOF_ASYNCHRONOUS_BAUDRATE);
	local_address += SIZEOF_ASYNCHRONOUS_BAUDRATE;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_data_bits),SIZEOF_ASYNCHRONOUS_DATABITS);
	local_address += SIZEOF_ASYNCHRONOUS_DATABITS;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_parity),SIZEOF_ASYNCHRONOUS_PARITY);
	local_address += SIZEOF_ASYNCHRONOUS_PARITY;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_stop_bits),SIZEOF_ASYNCHRONOUS_STOPBITS);
	local_address += SIZEOF_ASYNCHRONOUS_STOPBITS;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_Data_Interface.param_flow_control),SIZEOF_ASYNCHRONOUS_FLOWCONTROL);
	local_address += SIZEOF_ASYNCHRONOUS_FLOWCONTROL;
	/////////////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_SleepMode.param_sleep_reg),SIZEOF_SLEEP_MODE_REG);
	local_address += SIZEOF_SLEEP_MODE_REG;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_SleepMode.param_quit),SIZEOF_QUIET_TIMEOUT);
	local_address += SIZEOF_QUIET_TIMEOUT;
	memcpy(&data[local_address],(unsigned char *)&(ConfigRoot.G_Oper.SG_SleepMode.param_wakeup),SIZEOF_WAKEUP_TIMEOUT);
	local_address += SIZEOF_WAKEUP_TIMEOUT;
	///////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Wireless.SG_Uhf.param_channel_num,SIZEOF_CANNEL_NUMBER);
	local_address += SIZEOF_CANNEL_NUMBER;
	memcpy(&data[local_address],(char *)&ConfigRoot.G_Wireless.SG_Uhf.param_output_pow,SIZEOF_OUTPUT_POWER_LEVEL);
	local_address += SIZEOF_OUTPUT_POWER_LEVEL;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Wireless.SG_Uhf.param_modulation,SIZEOF_MODULATION_TYPE);
	local_address += SIZEOF_MODULATION_TYPE;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Wireless.SG_Uhf.param_fec,SIZEOF_FEC_TYPE);
	local_address += SIZEOF_FEC_TYPE;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Wireless.SG_Uhf.param_scram,SIZEOF_SCRAM);
	local_address += SIZEOF_SCRAM;
	memcpy(&data[local_address],(unsigned short *)&ConfigRoot.G_Wireless.SG_Uhf.param_carrier_freq_number,SIZEOF_CARRIER_FREQ_NUMBER);
	local_address += SIZEOF_CARRIER_FREQ_NUMBER;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Wireless.SG_Uhf.param_freq_number_symbolrate,SIZEOF_FREQ_NUMBER_SYMBOLRATE);
	local_address += SIZEOF_FREQ_NUMBER_SYMBOLRATE;
	///////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_NetProtSet.param_bridging_reg,SIZEOF_BRIDGING_PROTOCOL);
	local_address += SIZEOF_BRIDGING_PROTOCOL;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_NetProtSet.param_snmp_protocol_reg,SIZEOF_SNMP_PROTOCOL);
	local_address += SIZEOF_SNMP_PROTOCOL;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_NetProtSet.param_snmp_traptimeout,SIZEOF_SNMP_TRAP_TIMEOUT);
	local_address += SIZEOF_SNMP_TRAP_TIMEOUT;
	//////////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_WiFiSet.network_register,SIZEOF_NETWORK_REGISTER);
	local_address += SIZEOF_NETWORK_REGISTER;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_WiFiSet.access_point_name,SIZEOF_ACCESS_POINT_NAME);
	local_address += SIZEOF_ACCESS_POINT_NAME;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_WiFiSet.ssid,SIZEOF_SSID);
	local_address += SIZEOF_SSID;
	/////////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_TCPIPSet.param_tcpip_reg,SIZEOF_TCPIP_REGISTER);
	local_address += SIZEOF_TCPIP_REGISTER;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_TCPIPSet.param_ip_address,SIZEOF_IP_ADDRESS);
	local_address += SIZEOF_IP_ADDRESS;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_TCPIPSet.param_subnet_mask,SIZEOF_SUBNET_MASK);
	local_address += SIZEOF_SUBNET_MASK;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_TCPIPSet.param_default_gateway,SIZEOF_DEFAULT_GATEWAY);
	local_address += SIZEOF_DEFAULT_GATEWAY;
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_TCPIPSet.param_dns_server,SIZEOF_DNS_SERVER);
	local_address += SIZEOF_DNS_SERVER;
	////////////////////////////////////////////////////////
	memcpy(&data[local_address],(unsigned char *)&ConfigRoot.G_Network.SG_NetSec,SIZEOF_NETWORK_SECURITY);
	local_address += SIZEOF_NETWORK_SECURITY;


	//flashc_memcpy((void *)(INTERNAL_USER_CFG_FILE_ADDRESS),data, local_address,1); //write into internalflash
	at25dfx_erase(files_list[UCFG_FILE_INDEX].sector_number,(files_list[UCFG_FILE_INDEX].max_size) >> AT25DFX_SECTOR_BITS);
	unsigned char res = at25dfx_write_sector(files_list[UCFG_FILE_INDEX].sector_number,4,data);

	free(data);
	return res;
}

